package com.syh.jn.scm.domain.upstream.entity.finance;

import cn.redscarf.commons.util.bean.ExtBeanUtils;
import cn.redscarf.commons.util.other.ExtAssert;
import cn.redscarf.commons.spring.SpringContextUtils;
import cn.redscarf.commons.util.validator.ValidationUtils;
import cn.redscarf.commons.wrapper.Restrictions;
import cn.redscarf.commons.wrapper.Wrapper;
import com.syh.core.ddd.domain.AbstractSimpleAggregate;
import com.syh.core.ddd.domain.CodeExpEnum;
import com.syh.core.ddd.domain.CodeGenerateUtil;
import com.syh.jn.scm.domain.upstream.repository.finance.UpReceiptBillReadRepository;
import com.syh.jn.scm.dto.support.FilesDto;
import com.syh.jn.scm.dto.upstream.finance.UpStatementAccountBillMto;
import com.syh.jn.scm.dto.upstream.finance.UpStatementAccountBillSto;
import com.syh.jn.scm.exception.BusinessException;
import com.syh.jn.scm.service.api.upstream.finance.enums.UpStatementAccountBillEnum;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/**
 * 上游对账单
 */
@Data
@NoArgsConstructor
@EqualsAndHashCode(callSuper = true)
public class UpStatementAccountBill extends AbstractSimpleAggregate<Long> {
  /**
   * 归属端id
   */
  private Long businessEntityId;
  /**
   * 客户类型: 0上游, 1下游, 2物流
   */
  private Short customerType;
  /**
   * 收状态:-1未收款, 1 部分收款 2 完成收款
   */
  private Short state;
  /**
   * 客户id
   */
  private Long customerId;
  /**
   * 对账单编号
   */
  private String code;
  /**
   * 制单人id
   */
  private Long brokerageId;
  /**
   * 对账金额
   */
  private BigDecimal price;
  /**
   * 已收款金额
   */
  private BigDecimal makeCollectionsPrice;
  /**
   * 已生成收款单金额
   */
  private BigDecimal generatedCollectionsPrice;
  /**
   * 生成日期
   */
  private Long inputTimestamp;
  /**
   * 业务确认状态:0双方都未确认,1只有服务商确认,2只有对方确认,3代表双方都确认
   */
  private Short businessState;
  /**
   * 财务确认状态:0双方都未确认,1只有服务商确认,2只有对方确认,3代表双方都确认
   */
  private Short financeState;
  /**
   * 开票状态:-1未开票, 1 部分开票 2 完成开票
   */
  private Short ticketState;
  /**
   * 开票金额
   */
  private BigDecimal ticketPrice;
  /**
   * 已生成开票金额
   */
  private BigDecimal generatedTicketPrice;
  /**
   * 单据图片
   */
  private String secondSrcImages;
  /**
   * 对账单项
   */
  private List<UpStatementAccountBillItem> upStatementAccountBillItems;

  /**
   * 生成对账单
   *
   * @param sto
   */
  public UpStatementAccountBill(UpStatementAccountBillSto sto) {
    ExtAssert.notNull(sto, "对象为空");
    ValidationUtils.validate(sto);

    ExtBeanUtils.copyProperties(sto, this);
    this.customerType = Short.valueOf("0");
    this.createTimeStamp = System.currentTimeMillis();
    this.inputTimestamp = System.currentTimeMillis();
    this.price = BigDecimal.ZERO;
    //新建时默认到账金额为0
    this.makeCollectionsPrice = BigDecimal.ZERO;
    //新建时默认已生成到账金额为0
    this.generatedCollectionsPrice = BigDecimal.ZERO;
    //新建时默认开票金额为0
    this.ticketPrice = BigDecimal.ZERO;
    //新建时默认已生成开票金额为0
    this.generatedTicketPrice = BigDecimal.ZERO;
    this.businessState = UpStatementAccountBillEnum.BOTH_STAYCONFIRM.getStatus();
    this.financeState = UpStatementAccountBillEnum.BOTH_STAYCONFIRM.getStatus();
    this.ticketState = UpStatementAccountBillEnum.NOT_INVOICE.getStatus();
    //新建时候未付款
    this.state = UpStatementAccountBillEnum.MONEY_UNRECEIVED.getStatus();
    this.setUuid(UUID.randomUUID().toString());
    this.setCode(CodeGenerateUtil.codeGenerate(CodeExpEnum.STATEMENT_ACCOUNT_BILL_EXP.getCodeExp(), sto.getCustomerId()));

    this.upStatementAccountBillItems = new ArrayList<>();
    sto.getItems().forEach(item -> {
      UpStatementAccountBillItem billItem = new UpStatementAccountBillItem(item, this.customerId);
      this.upStatementAccountBillItems.add(billItem);
    });
    this.priceCount();
  }

  public void modify(UpStatementAccountBillMto mto) {
    ExtAssert.notNull(mto, "对象为空");
    ValidationUtils.validate(mto);

    ExtBeanUtils.copyProperties(mto, this, false);
    this.lastUpdateTimeStamp =  System.currentTimeMillis();
    this.inputTimestamp = System.currentTimeMillis();
    this.price = BigDecimal.ZERO;

    this.upStatementAccountBillItems = new ArrayList<>();
    mto.getItems().forEach(item -> {
      UpStatementAccountBillItem billItem = new UpStatementAccountBillItem(item, this.customerId);
      this.upStatementAccountBillItems.add(billItem);
    });
    this.priceCount();
  }

  /**
   * 计算对账金额
   */
  private void priceCount(){
    this.upStatementAccountBillItems.forEach(billItem -> {
      switch (billItem.getSourceType()) {
        //销售单
        case 2:
          this.price = this.price.add(billItem.getTotalAmount());
          break;
        //销售退货单
        case 3:
          this.price = this.price.subtract(billItem.getTotalAmount());
          break;
        //收入单
        case 4:
          this.price = this.price.add(billItem.getTotalAmount());
          break;
        //费用单
        case 5:
          this.price = this.price.subtract(billItem.getTotalAmount());
          break;
      }
    });
  }
  /**
   * 业务确认
   */
  public void businessConfirmation() {

    if (UpStatementAccountBillEnum.BOTH_STAYCONFIRM.getStatus().equals(this.businessState)) {
      this.businessState = UpStatementAccountBillEnum.OTHERPARTY_CONFIRM.getStatus();
    } else if (UpStatementAccountBillEnum.OUR_CONFIRM.getStatus().equals(this.businessState)) {
      this.businessState = UpStatementAccountBillEnum.BOTH_CONFIRM.getStatus();
    }
  }

  /**
   * 业务取消确认
   */
  public void businessCancelConfirmation() {
    if (!(this.generatedCollectionsPrice.compareTo(BigDecimal.ZERO) == 0)
            || !(this.generatedTicketPrice.compareTo(BigDecimal.ZERO) == 0)) {
      throw new BusinessException("该对账单已生成收款单或已生成发票，取消失败！");
    }
    if (!this.state.equals(UpStatementAccountBillEnum.MONEY_UNRECEIVED.getStatus())
            || !this.ticketState.equals(UpStatementAccountBillEnum.NOT_INVOICE.getStatus())) {
      throw new BusinessException("该对账单已收款或已开发票，取消失败！");
    }

    if (UpStatementAccountBillEnum.OTHERPARTY_CONFIRM.getStatus().equals(this.businessState)) {
      this.businessState = UpStatementAccountBillEnum.BOTH_STAYCONFIRM.getStatus();
    } else if (UpStatementAccountBillEnum.BOTH_CONFIRM.getStatus().equals(this.businessState)) {
      this.businessState = UpStatementAccountBillEnum.OUR_CONFIRM.getStatus();
    }
  }

  /**
   * 财务确认
   */
  public void financeConfirmation() {
    if (UpStatementAccountBillEnum.BOTH_STAYCONFIRM.getStatus().equals(this.financeState)) {
      this.financeState = UpStatementAccountBillEnum.OTHERPARTY_CONFIRM.getStatus();
    } else if (UpStatementAccountBillEnum.OUR_CONFIRM.getStatus().equals(this.financeState)) {
      this.financeState = UpStatementAccountBillEnum.BOTH_CONFIRM.getStatus();
    }
  }

  /**
   * 财务取消确认
   */
  public void financeCancelConfirmation() {
    if (!(this.generatedCollectionsPrice.compareTo(BigDecimal.ZERO) == 0)
            || !(this.generatedTicketPrice.compareTo(BigDecimal.ZERO) == 0)) {
      throw new BusinessException("该对账单已生成收款单或已生成发票，取消失败！");
    }
    if (!this.state.equals(UpStatementAccountBillEnum.MONEY_UNRECEIVED.getStatus())
            || !this.ticketState.equals(UpStatementAccountBillEnum.NOT_INVOICE.getStatus())) {
      throw new BusinessException("该对账单已收款或已开发票，取消失败！");
    }

    if (UpStatementAccountBillEnum.OTHERPARTY_CONFIRM.getStatus().equals(this.financeState)) {
      this.financeState = UpStatementAccountBillEnum.BOTH_STAYCONFIRM.getStatus();
    } else if (UpStatementAccountBillEnum.BOTH_CONFIRM.getStatus().equals(this.financeState)) {
      this.financeState = UpStatementAccountBillEnum.OUR_CONFIRM.getStatus();
    }
  }

  /**
   * 设置到账金额
   */
  public void accountAmount(BigDecimal money) {
    this.makeCollectionsPrice = this.makeCollectionsPrice.add(money);
    if (this.makeCollectionsPrice.doubleValue() > this.price.doubleValue()) {
      throw new BusinessException("开票金额大于对账单收款金额");
    }
    if (this.makeCollectionsPrice.doubleValue() < this.price.doubleValue()) {
      this.state = UpStatementAccountBillEnum.PART_MONEY_RECEIVED.getStatus();
    }
    if (this.makeCollectionsPrice.doubleValue() == this.price.doubleValue()) {
      this.state = UpStatementAccountBillEnum.MONEY_RECEIVED.getStatus();
    }
  }

  /**
   * 取消到账
   */
  public void subAccountAmount(BigDecimal money) {
    this.makeCollectionsPrice = this.makeCollectionsPrice.subtract(money);
    if (this.makeCollectionsPrice.doubleValue() == 0) {
      this.state = UpStatementAccountBillEnum.MONEY_UNRECEIVED.getStatus();
    }
    if (this.makeCollectionsPrice.doubleValue() != 0 && this.makeCollectionsPrice.doubleValue() < this.price.doubleValue()) {
      this.state = UpStatementAccountBillEnum.PART_MONEY_RECEIVED.getStatus();
    }
  }

  /**
   * 增加已生成开票金额,以及更改开票状态
   */
  public void addGeneratedTicketPrice(BigDecimal money) {
    this.generatedTicketPrice = this.generatedTicketPrice.add(money);
    if (this.generatedTicketPrice.doubleValue() > this.price.doubleValue()) {
      throw new BusinessException("已生成开票金额大于对账单金额");
    }
  }

  /**
   * 减少已生成开票金额,以及更改开票状态
   */
  public void subGeneratedTicketPrice(BigDecimal money) {
    this.generatedTicketPrice = this.generatedTicketPrice.subtract(money);
    if (this.generatedTicketPrice.doubleValue() < 0 ) {
      throw new BusinessException("应减少的已生成开票金额异常，小于0");
    }
  }

  /**
   * 设置开票金额,以及开票状态
   */
  public void invoiceValue(BigDecimal money) {
    this.ticketPrice = this.ticketPrice.add(money);

    if (this.ticketPrice.doubleValue() > this.price.doubleValue()) {
      throw new BusinessException("开票金额大于对账单金额");
    }
    if (this.ticketPrice.doubleValue() < this.price.doubleValue()) {
      this.ticketState = UpStatementAccountBillEnum.PART_INVOICED.getStatus();
    }
    if (this.ticketPrice.doubleValue() == this.price.doubleValue()) {
      this.ticketState = UpStatementAccountBillEnum.FINISH_INVOICED.getStatus();
    }
  }

  /**
   * 数据销毁
   */
  public void destroy() {
    if (!UpStatementAccountBillEnum.BOTH_STAYCONFIRM.getStatus().equals(this.businessState)
            || !UpStatementAccountBillEnum.BOTH_STAYCONFIRM.getStatus().equals(this.financeState)
            || !UpStatementAccountBillEnum.NOT_INVOICE.getStatus().equals(this.ticketState)) {
      throw new BusinessException("订单处于确认状态,删除失败!");
    }

    //查看收款是否存在对账信息
    UpReceiptBillReadRepository receiptBillReadRepository = (UpReceiptBillReadRepository) SpringContextUtils.getBean(UpReceiptBillReadRepository.class);
    Wrapper receiptBillWrapper = Wrapper.build();
    receiptBillWrapper.append(Restrictions.eq("statementOfAccountId", this.id));
    Integer receiptCount = receiptBillReadRepository.getCount(receiptBillWrapper);
    if (receiptCount > 0) {
      throw new BusinessException("该数据在收款单存在记录,删除失败!");
    }

  }

  /**
   * 上传图片
   *
   * @param dto
   */
  public void upload(FilesDto dto) {
    this.secondSrcImages = dto.getFiles();
  }
}
